#!/usr/bin/env node

const fs = require('fs');
const chalk = require('chalk');
const semver = require('semver');

const isDebug =false


const DEPLOY_SCHEMA = {
  name: '',
  script: "",
  host: '',
  port: 22,
  username: '',
  password: '',
  backupDir:'',
  webDir: ''
};

const PRIVATE_KEY_DEPLOY_SCHEMA = {
  name: '',
  script: "",
  host: '',
  port: 22,
  backupDir:'',
  webDir: ''
};

// 开始部署日志
function startLog(...content) {
  console.log(chalk.magenta(...content));
}

// 信息日志
function infoLog(...content) {
  console.log(chalk.blue(...content));
}

// 成功日志
function successLog(...content) {
  console.log(chalk.green(...content));
}

// 错误日志
function errorLog(...content) {
  console.log(chalk.red(...content));
}

// 下划线重点输出
function underlineLog(content) {
  return chalk.blue.underline.bold(`${content}`);
}

// 检查node版本是否符合特定范围
function checkNodeVersion(wanted, id) {
  if (!semver.satisfies(process.version, wanted)) {
    errorLog(`You ar using Node ${process.version}, but this version of ${id} requres Node ${wanted} .\nPlease upgrage your Node version.`);
    process.exit(1);
  }
}

// 检查配置是否符合特定schema
function checkConfigScheme(configKey, configObj, privateKey) {
  isDebug && console.log(`checkConfigScheme configKey=${configKey} , configObj=${JSON.stringify(configObj)} ,privateKey=${privateKey}`)
  let deploySchemaKeys = null;
  const configKeys = Object.keys(configObj);
  const neededKeys = [];
  const unConfigedKeys = [];
  let configValid = true;
  if (privateKey) {
    deploySchemaKeys = Object.keys(PRIVATE_KEY_DEPLOY_SCHEMA);
  } else {
    deploySchemaKeys = Object.keys(DEPLOY_SCHEMA);
  }
  for (let key of deploySchemaKeys) {
    if (!configKeys.includes(key)) {
      neededKeys.push(key);
    }
    if (configObj[key] === '') {
      unConfigedKeys.push(key);
    }
  }
  if (neededKeys.length > 0) {
    errorLog(`${configKey}缺少${neededKeys.join(',')}配置，请检查配置`);
    configValid = false;
  }
  if (unConfigedKeys.length > 0) {
    errorLog(`${configKey}中的${unConfigedKeys.join(', ')}暂未配置，请设置该配置项`);
    configValid = false;
  }
  return configValid;
}

 async function loadDeployConfig (deployConfigPath){
  try {
    const module = await import(deployConfigPath)
    // console.log("loadDeployConfig",deployConfig);
    //使用默认导出
    return module.default
  } catch (error) {
    console.error(`Failed to load deploy config: ${error}`);
    return {}
  }
};

function nodejsVer(){
  let ver = parseInt(process.version.replace("v","").split('.')[0])
  return ver
};


function readDeployConfigFile(deployConfigPath,command){
  return new Promise( async (resolve,reject)=>{
    if (exists(deployConfigPath)) {
      //ESM, Error [ERR_REQUIRE_ESM]: require() of ES Module
      const config = nodejsVer() <= 14 ?require(deployConfigPath): await loadDeployConfig(deployConfigPath)
      //const config = require(deployConfigPath);
      // const config = await loadDeployConfig(deployConfigPath)
      //console.log("config ",config)
      const { privateKey, passphrase, projectName } = config;
      //console.log(` privateKey =${privateKey} projectName=${projectName}`)
      const commandCfg= config[command]
      if (!checkConfigScheme(command, commandCfg, privateKey)) {
        return reject(false);
      }
      return resolve({
        "command":command,
        "privateKey":privateKey,
        "passphrase" : passphrase,
        "projectName" : projectName,
         ...commandCfg
      });
    }
    infoLog(`缺少部署相关的配置，请运行${underlineLog('deploy init')}下载部署配置`);
    return reject(false);
  }).catch(err=>{
    infoLog(`${err}`);
    return false;
  })
};

// 检查deploy配置是否合理
async function checkDeployConfig(deployConfigPath) {
  isDebug && console.log("deployConfigPath",deployConfigPath)
  if (exists(deployConfigPath)) {
    //ESM, Error [ERR_REQUIRE_ESM]: require() of ES Module
    const config = nodejsVer() <= 14 ?require(deployConfigPath): await loadDeployConfig(deployConfigPath)
    //const config = require(deployConfigPath);
    //const config = await loadDeployConfig(deployConfigPath)
    //console.log("_config", config)
    const { privateKey, passphrase, projectName } = config;
    //console.log(` privateKey =${privateKey} projectName=${projectName}`)
    const keys = Object.keys(config);
    const configs = [];
    for (let key of keys) {
      if (config[key] instanceof Object) {
        if (!checkConfigScheme(key, config[key], privateKey)) {
          return false;
        }
        config[key].command = key;
        config[key].privateKey = privateKey;
        config[key].passphrase = passphrase;
        config[key].projectName = projectName;
        configs.push(config[key]);
      }
    }
    return configs;
  }
  infoLog(`缺少部署相关的配置，请运行${underlineLog('deploy init')}下载部署配置`);
  return false;
}

/**
 * 获取当前时间
 * @param format 默认格式：{y}-{M}-{d} {h}:{i}:{s} 星期{w}  {y}年{M}月{d}日 {h}:{i}:{s} 星期{w}
 * @returns {string}
 */
function nowDate(format='{y}-{M}-{d} {h}:{m}:{s}') {
  const date = new Date()
  const dateObj = {
      y: date.getFullYear(), // 获取完整的年份(4位)
      M: date.getMonth() + 1, // 获取当前月份(0-11,0代表1月)
      d: date.getDate(), // 获取当前日(1-31)
      h: date.getHours(), // 获取当前小时(0 ~ 23)
      m: date.getMinutes(), // 获取当前分钟(0 ~ 59)
      s: date.getSeconds(), // 获取当前秒数(0 ~ 59)
      w: '日一二三四五六'.charAt(date.getDay()), // 获取当前星期几(0 ~ 6,0代表星期天)
    }
  //不足两位数进行补0
  Object.keys(dateObj).forEach(key => {
    if (dateObj[key] < 10) dateObj[key] = `0${dateObj[key]}`
  })
  /*
  const str = format.replace(/{(y|M|d|h|m|s|w)+}/g, (result, key) => {
    let value = dateObj[key]
    return value || 0
  })
  */
  return format.replace(/{(y|M|d|h|m|s|w)+}/g,(_,key)=>dateObj[key]||0)

}

function exists(file){
  try {
    //读取文件信息  获取文件信息状态
    fs.statSync(file)
    return true
  } catch (error) {
    if(error.code === "ENOENT"){
      return false
    }else{
      throw (error)
    }
  }
}

module.exports = {
  startLog,
  infoLog,
  successLog,
  errorLog,
  underlineLog,
  checkNodeVersion,
  checkDeployConfig,
  nowDate,
  exists,
  readDeployConfigFile,
  isDebug
};
